<template>
  <div class="earth-container">
    <div ref="earthRef" class="earth-canvas"></div>
    <div v-if="showChinaLabel" class="china-label">中国</div>
  </div>
</template>

<script setup lang="ts">
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js'
import { onMounted, ref } from 'vue'
import worldGeoData from '@/assets/json/worldGeoData.json'

// 声明全局变量类型
declare global {
  interface Window {
    innerWidth: number;
    innerHeight: number;
    devicePixelRatio: number;
  }
}

const earthRef = ref<HTMLElement | null>(null)
const showChinaLabel = ref(true)

onMounted(() => {
  if (earthRef.value) {
    initEarth()
  }
})

const initEarth = () => {
  // 提前声明变量
  let scene: THREE.Scene
  let camera: THREE.PerspectiveCamera
  let renderer: THREE.WebGLRenderer
  let css3DRenderer: CSS3DRenderer
  let controls: any
  let earth: THREE.Mesh
  let outerGlowSphere: THREE.Mesh
  let innerGlowSphere: THREE.Mesh
  let outerGlowMaterial: THREE.ShaderMaterial
  let innerGlowMaterial: THREE.ShaderMaterial
  let chinaX: number, chinaY: number, chinaZ: number
  let chinaInfoPanel: CSS3DObject
  let directionalLight: THREE.DirectionalLight
  
  // 创建场景
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x000000)
  
  // 创建相机
  camera = new THREE.PerspectiveCamera(
    45,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  )
  camera.position.set(0, 0, 2.5)
  
  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setPixelRatio(window.devicePixelRatio)
  
  // 创建CSS3D渲染器
  try {
    css3DRenderer = new CSS3DRenderer()
    css3DRenderer.setSize(window.innerWidth, window.innerHeight)
    
    if (earthRef.value) {
      earthRef.value.innerHTML = ''
      // 先添加WebGL渲染器，再添加CSS3D渲染器以确保正确的层叠顺序
      earthRef.value.appendChild(renderer.domElement)
      earthRef.value.appendChild(css3DRenderer.domElement)
      // 设置CSS3D渲染器容器的样式以确保正确显示
      css3DRenderer.domElement.style.position = 'absolute'
      css3DRenderer.domElement.style.top = '0'
      css3DRenderer.domElement.style.left = '0'
      css3DRenderer.domElement.style.pointerEvents = 'none'
      css3DRenderer.domElement.style.zIndex = '1000'
    }
  } catch (error) {
    console.error('CSS3DRenderer初始化错误:', error)
  }
  
  // 创建OrbitControls
  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true // 启用阻尼效果
  controls.dampingFactor = 0.05 // 阻尼系数
  controls.rotateSpeed = 0.5 // 旋转速度
  controls.zoomSpeed = 1.0 // 缩放速度
  controls.panSpeed = 0.5 // 平移速度
  
  // 禁止平移，只允许旋转和缩放
  controls.enablePan = false
  
  // 设置缩放范围
  controls.minDistance = 1.5
  controls.maxDistance = 5
  
  // 创建地球几何体
  const geometry = new THREE.SphereGeometry(1, 64, 64)
  
  // 创建不透明材质
  const material = new THREE.MeshPhongMaterial({
    color: 0x2a6fc4,
    specular: 0x333333,
    shininess: 30,
    transparent: false, // 不透明
    opacity: 1.0
  })
  
  // 创建地球网格
  earth = new THREE.Mesh(geometry, material)
  console.log('地球对象已创建:', earth)
  console.log('地球对象类型:', typeof earth)
  scene.add(earth)
  console.log('地球已添加到场景:', scene.children.includes(earth))
  
  // 创建地理边界线
  createWorldBoundaries(scene)
  
  // 创建边缘向内发光效果 - 使用双层发光增强效果
  // 外层发光（较强烈，向外扩散）
  const outerGlowGeometry = new THREE.SphereGeometry(1.02, 64, 64)
  outerGlowMaterial = new THREE.ShaderMaterial({
    uniforms: {
      "c":   { value: 0.3 },
      "p":   { value: 8.0 },
      glowColor: { value: new THREE.Color(0x4a90e2) },
      viewVector: { value: camera.position }
    },
    vertexShader: `
      uniform vec3 viewVector;
      uniform float c;
      uniform float p;
      varying float intensity;
      void main() {
        vec3 vNormal = normalize(normalMatrix * normal);
        vec3 vNormel = normalize(normalMatrix * viewVector);
        float dotProduct = dot(vNormal, vNormel);
        intensity = pow(c - dotProduct, p);
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }`,
    fragmentShader: `
      uniform vec3 glowColor;
      varying float intensity;
      void main() {
        vec3 glow = glowColor * intensity;
        float maxIntensity = 0.3;
        float finalIntensity = min(intensity, maxIntensity);
        gl_FragColor = vec4(glow, finalIntensity);
      }`,
    side: THREE.BackSide,
    blending: THREE.AdditiveBlending,
    transparent: true,
    depthWrite: false,
    opacity: 0.7 // 添加整体透明度控制
  })
  
  outerGlowSphere = new THREE.Mesh(outerGlowGeometry, outerGlowMaterial)
  scene.add(outerGlowSphere)
  
  // 内层发光（较柔和，向内扩散）
  const innerGlowGeometry = new THREE.SphereGeometry(1.01, 64, 64)
  innerGlowMaterial = new THREE.ShaderMaterial({
    uniforms: {
      "c":   { value: 0.25 },
      "p":   { value: 4.0 },
      glowColor: { value: new THREE.Color(0x4a90e2) },
      viewVector: { value: camera.position }
    },
    vertexShader: `
      uniform vec3 viewVector;
      uniform float c;
      uniform float p;
      varying float intensity;
      void main() {
        vec3 vNormal = normalize(normalMatrix * normal);
        vec3 vNormel = normalize(normalMatrix * viewVector);
        float dotProduct = dot(vNormal, vNormel);
        intensity = pow(c - dotProduct, p);
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }`,
    fragmentShader: `
      uniform vec3 glowColor;
      varying float intensity;
      void main() {
        vec3 glow = glowColor * intensity;
        float maxIntensity = 0.4;
        float finalIntensity = min(intensity, maxIntensity);
        gl_FragColor = vec4(glow, finalIntensity);
      }`,
    side: THREE.BackSide,
    blending: THREE.AdditiveBlending,
    transparent: true,
    depthWrite: false,
    opacity: 0.5
  })
  
  innerGlowSphere = new THREE.Mesh(innerGlowGeometry, innerGlowMaterial)
  scene.add(innerGlowSphere)
  
  // 添加鼠标交互
  const raycaster = new THREE.Raycaster()
  const mouse = new THREE.Vector2()
  
  // 创建中国区域的标记点（北京位置）
  const chinaLat = 39.55
  const chinaLon = 116.20
  const phi = (90 - chinaLat) * Math.PI / 180
  const theta = (chinaLon + 180) * Math.PI / 180
  const chinaRadius = 1.02
  chinaX = -Math.sin(phi) * Math.cos(theta) * chinaRadius
  chinaY = Math.cos(phi) * chinaRadius
  chinaZ = Math.sin(phi) * Math.sin(theta) * chinaRadius
  
  // 声明这些变量以便在其他地方使用
  let chinaMarker: THREE.Mesh
  let chinaGlow: THREE.Mesh
  
  // 创建一个可见的标记点来标识中国位置
  const markerGeometry = new THREE.SphereGeometry(0.03, 16, 16)
  const markerMaterial = new THREE.MeshBasicMaterial({
    color: 0xff0000,
    transparent: true,
    opacity: 0.8
  })
  chinaMarker = new THREE.Mesh(markerGeometry, markerMaterial)
  chinaMarker.position.set(chinaX, chinaY, chinaZ)
  scene.add(chinaMarker)
  
  // 创建一个发光效果来突出显示中国位置
  const glowGeometry = new THREE.SphereGeometry(0.05, 16, 16)
  const glowMaterial = new THREE.MeshBasicMaterial({
    color: 0xff6b6b,
    transparent: true,
    opacity: 0.3
  })
  chinaGlow = new THREE.Mesh(glowGeometry, glowMaterial)
  chinaGlow.position.set(chinaX, chinaY, chinaZ)
  scene.add(chinaGlow)
  
  // 创建一个始终面向相机的3D信息面板
  // 更新信息面板位置的函数
  const createInfoPanel = () => {
    // 创建HTML元素作为信息面板
    const panelElement = document.createElement('div');
    panelElement.className = 'china-info-panel';
    panelElement.innerHTML = `
      <div class="info-content">
        <h2>中国</h2>
        <div class="info-section">
          <h3>基本信息</h3>
          <p><strong>首都：</strong>北京</p>
          <p><strong>人口：</strong>约14.1亿</p>
          <p><strong>面积：</strong>960万平方公里</p>
          <p><strong>语言：</strong>汉语</p>
          <p><strong>货币：</strong>人民币</p>
        </div>
        <div class="info-section">
          <h3>地理与文化</h3>
          <p>位于东亚的文明古国，拥有五千年历史</p>
          <p>以长城、故宫、熊猫闻名世界</p>
          <p>地形多样，从高原到平原，气候丰富</p>
        </div>
        <div class="info-section">
          <h3>经济与发展</h3>
          <p>世界第二大经济体</p>
          <p>制造业和科技产业发达</p>
          <p>高铁网络世界领先</p>
        </div>
      </div>
    `;
    
    // 创建CSS3D对象
    const infoPanel = new CSS3DObject(panelElement);
    
    // 设置信息面板的位置，使其位于中国位置稍上方
    // 使用球面坐标计算，使面板位于中国位置正上方一点距离处
    const panelRadius = 1.05; // 稍微高于地球表面
    infoPanel.position.set(chinaX * panelRadius, chinaY * panelRadius, chinaZ * panelRadius);
    
    // 将信息面板添加到场景中
    scene.add(infoPanel);
    
    return infoPanel;
  };
  
  // 创建信息面板
  chinaInfoPanel = createInfoPanel();
  

  
  // 实现createWorldBoundaries函数，处理GeoJSON数据并创建边界线
  function createWorldBoundaries(scene: THREE.Scene) {
    // 将GeoJSON数据转换为THREE.Line对象并添加到场景中
    // worldGeoData是从外部导入的GeoJSON数据
    
    // 遍历features数组中的每个feature
    worldGeoData.features.forEach((feature: any) => {
      const coordinates = feature.geometry.coordinates;
      const type = feature.geometry.type;
      
      // 根据几何类型处理坐标
      if (type === 'MultiPolygon') {
        coordinates.forEach((polygon: any) => {
          polygon.forEach((ring: any) => {
            createLineFromCoordinates(ring, scene);
          });
        });
      } else if (type === 'Polygon') {
        coordinates.forEach((ring: any) => {
          createLineFromCoordinates(ring, scene);
        });
      } else if (type === 'LineString') {
        createLineFromCoordinates(coordinates, scene);
      } else if (type === 'MultiLineString') {
        coordinates.forEach((line: any) => {
          createLineFromCoordinates(line, scene);
        });
      }
    });
  }
  
  // 根据经纬度坐标创建线条
  function createLineFromCoordinates(coords: number[][], scene: THREE.Scene) {
    const points: THREE.Vector3[] = [];
    
    // 将经纬度坐标转换为三维空间坐标
    coords.forEach(coord => {
      const [longitude, latitude] = coord;
      const phi = (90 - latitude) * Math.PI / 180;
      const theta = (longitude + 180) * Math.PI / 180;
      
      // 地球半径稍微放大一点，使边界线在地球表面上方
      const radius = 1.001;
      const x = -Math.sin(phi) * Math.cos(theta) * radius;
      const y = Math.cos(phi) * radius;
      const z = Math.sin(phi) * Math.sin(theta) * radius;
      
      points.push(new THREE.Vector3(x, y, z));
    });
    
    // 创建线条几何体
    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    
    // 创建线条材质
    const material = new THREE.LineBasicMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.5
    });
    
    // 创建线条对象并添加到场景中
    const line = new THREE.Line(geometry, material);
    scene.add(line);
  }
  
  // 添加光源，调整位置使光照中心位于屏幕中央
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.3) // 减弱环境光强度
  scene.add(ambientLight)
  
  // 调整方向光位置，使其从正面照射地球
  directionalLight = new THREE.DirectionalLight(0xffffff, 0.5) // 减弱方向光强度
  directionalLight.position.set(0, 0, 5)
  scene.add(directionalLight)
  
  // 可选：添加点光源增强效果
  const pointLight = new THREE.PointLight(0xffffff, 0.2) // 减弱点光源强度
  pointLight.position.set(2, 2, 2)
  scene.add(pointLight)
  
  // 更新光源位置，使其跟随相机移动，保持光照在屏幕正前方
  const updateLights = () => {
    if (directionalLight && camera) {
      directionalLight.position.copy(camera.position).normalize().multiplyScalar(5)
    }
  }
  
  // 添加计算标签在屏幕上的位置的函数
  const updateLabelPosition = () => {
    if (typeof chinaX === 'undefined' || typeof chinaY === 'undefined' || typeof chinaZ === 'undefined') {
      return
    }
    
    const vector = new THREE.Vector3(chinaX, chinaY, chinaZ)
    vector.project(camera)
    const x = (vector.x * 0.5 + 0.5) * window.innerWidth
    const y = (-vector.y * 0.5 + 0.5) * window.innerHeight
    
    // 更新标签位置
    if (showChinaLabel.value && earthRef.value) {
      const label = document.querySelector('.china-label') as HTMLElement
      if (label) {
        label.style.left = `${x}px`
        label.style.top = `${y}px`
      }
    }
  }
  
  // 动画循环
  const animate = () => {
    requestAnimationFrame(animate)
    
    // 添加调试信息
    console.log('动画循环执行中...')
    
    // 检查是否有错误并打印到控制台
    try {
      // 更新OrbitControls
      if (controls) {
        controls.update()
      }
      
      // 更新光源位置
      updateLights()
      
      // 地球和发光效果一起自转
  console.log('检查地球对象是否存在:', !!earth)
  if (earth) {
    console.log('地球旋转前角度:', earth.rotation.y)
    earth.rotation.y += 0.002
    console.log('地球旋转后角度:', earth.rotation.y)
  } else {
    console.log('地球对象未定义')
  }
  if (outerGlowSphere) {
    outerGlowSphere.rotation.y += 0.002
  }
  if (innerGlowSphere) {
    innerGlowSphere.rotation.y += 0.002
  }
      
      // 更新发光材质的视图向量
      if (outerGlowMaterial && outerGlowMaterial.uniforms && outerGlowMaterial.uniforms.viewVector) {
        outerGlowMaterial.uniforms.viewVector.value = camera.position
      }
      if (innerGlowMaterial && innerGlowMaterial.uniforms && innerGlowMaterial.uniforms.viewVector) {
        innerGlowMaterial.uniforms.viewVector.value = camera.position
      }
      
      // 更新标签位置
      updateLabelPosition()
      
      // 更新信息面板方向，使其始终面向相机
      if (chinaInfoPanel && camera) {
        // 设置信息面板朝向相机
        chinaInfoPanel.lookAt(camera.position);
      }
      
      if (renderer && scene && camera) {
        renderer.render(scene, camera)
      }
      
      // 渲染CSS3D对象
      if (css3DRenderer && scene && camera) {
        css3DRenderer.render(scene, camera)
      }
    } catch (error) {
      console.error('动画循环错误:', error)
    }
  }
  
  // 移除鼠标点击事件处理，因为信息面板现在始终显示
  
  // 窗口大小调整
  const handleResize = () => {
    if (camera && renderer) {
      camera.aspect = window.innerWidth / window.innerHeight
      camera.updateProjectionMatrix()
      renderer.setSize(window.innerWidth, window.innerHeight)
      if (css3DRenderer) {
        css3DRenderer.setSize(window.innerWidth, window.innerHeight)
      }
    }
  }
  
  window.addEventListener('resize', handleResize)
  
  // 开始动画
  animate()
}
</script>

<style scoped>
.earth-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
  position: relative;
}

.earth-canvas {
  width: 100%;
  height: 100%;
}

.china-info-panel {
  position: absolute;
  background: rgba(0, 0, 0, 0.8);
  border: 2px solid #4a90e2;
  border-radius: 20px;
  padding: 20px;
  width: 350px;
  height: 300px;
  z-index: 1000; /* 提高z-index确保在最上层 */
  backdrop-filter: blur(10px);
  box-shadow: 0 0 20px rgba(74, 144, 226, 0.5);
  transform: translate(-50%, -50%);
  pointer-events: auto; /* 允许面板交互 */
}

.info-content h2 {
  color: #4a90e2;
  margin-top: 0;
  text-align: center;
  font-size: 24px;
  font-weight: bold;
}

.info-content h3 {
  color: #4a90e2;
  margin: 10px 0 5px 0;
  font-size: 16px;
  border-bottom: 1px solid #4a90e2;
  padding-bottom: 3px;
}

.info-content p {
  color: white;
  font-size: 12px;
  line-height: 1.4;
  margin: 5px 0;
}

.china-label {
  position: absolute;
  color: #ff6b6b;
  font-size: 14px;
  font-weight: bold;
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
  pointer-events: none;
  z-index: 10;
  transform: translate(-50%, -50%);
}
</style>